/**
 * 模型对比WebSocket服务
 * 处理实时推送和状态管理
 */

import { EventEmitter } from 'events';

export interface ComparisonProgress {
  type: 'progress' | 'result' | 'complete' | 'error' | 'connected';
  model?: string;
  status?: string;
  result?: any;
  aggregation?: any;
  error?: string;
  timestamp: string;
}

export class ComparisonWebSocketService extends EventEmitter {
  private ws: WebSocket | null = null;
  private sessionId: string | null = null;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;
  private reconnectDelay = 1000;
  private pingInterval: NodeJS.Timeout | null = null;
  private isConnecting = false;
  private messageQueue: string[] = [];

  constructor() {
    super();
    this.setupEventHandlers();
  }

  /**
   * 连接到WebSocket服务器
   * @param sessionId 会话ID
   * @returns Promise<void>
   */
  async connect(sessionId: string): Promise<void> {
    if (this.isConnecting || (this.ws && this.ws.readyState === WebSocket.OPEN)) {
      console.log('WebSocket already connected or connecting');
      return;
    }

    this.sessionId = sessionId;
    this.isConnecting = true;

    return new Promise((resolve, reject) => {
      try {
        // 构建WebSocket URL
        const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
        const host = process.env.REACT_APP_WS_HOST || window.location.host;
        const wsUrl = `${protocol}//${host}/api/v1/comparisons/ws/${sessionId}`;

        this.ws = new WebSocket(wsUrl);

        // 连接成功
        this.ws.onopen = () => {
          console.log(`WebSocket connected for session: ${sessionId}`);
          this.isConnecting = false;
          this.reconnectAttempts = 0;
          this.startPing();
          this.flushMessageQueue();
          this.emit('connected', { sessionId });
          resolve();
        };

        // 接收消息
        this.ws.onmessage = (event) => {
          try {
            const message: ComparisonProgress = JSON.parse(event.data);
            this.handleMessage(message);
          } catch (error) {
            console.error('Failed to parse WebSocket message:', error);
          }
        };

        // 连接错误
        this.ws.onerror = (error) => {
          console.error('WebSocket error:', error);
          this.isConnecting = false;
          this.emit('error', { error: 'WebSocket connection error' });
          reject(error);
        };

        // 连接关闭
        this.ws.onclose = (event) => {
          console.log('WebSocket closed:', event.code, event.reason);
          this.isConnecting = false;
          this.stopPing();
          this.emit('disconnected', { sessionId, code: event.code, reason: event.reason });
          
          // 自动重连
          if (this.shouldReconnect(event.code)) {
            this.scheduleReconnect();
          }
        };

      } catch (error) {
        this.isConnecting = false;
        console.error('Failed to create WebSocket:', error);
        reject(error);
      }
    });
  }

  /**
   * 断开WebSocket连接
   */
  disconnect(): void {
    if (this.ws) {
      this.stopPing();
      this.ws.close(1000, 'Client disconnecting');
      this.ws = null;
      this.sessionId = null;
      this.reconnectAttempts = 0;
    }
  }

  /**
   * 发送消息
   * @param message 消息内容
   */
  send(message: any): void {
    const data = typeof message === 'string' ? message : JSON.stringify(message);
    
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(data);
    } else {
      // 加入消息队列，等待连接恢复后发送
      this.messageQueue.push(data);
      console.log('WebSocket not ready, message queued');
    }
  }

  /**
   * 处理接收到的消息
   * @param message 消息对象
   */
  private handleMessage(message: ComparisonProgress): void {
    console.log('Received message:', message);

    switch (message.type) {
      case 'connected':
        this.emit('connected', message);
        break;
      case 'progress':
        this.emit('progress', message);
        break;
      case 'result':
        this.emit('result', message);
        break;
      case 'complete':
        this.emit('complete', message);
        break;
      case 'error':
        this.emit('error', message);
        break;
      default:
        console.warn('Unknown message type:', message.type);
    }
  }

  /**
   * 设置事件处理器
   */
  private setupEventHandlers(): void {
    // 处理页面卸载
    if (typeof window !== 'undefined') {
      window.addEventListener('beforeunload', () => {
        this.disconnect();
      });

      // 处理页面可见性变化
      document.addEventListener('visibilitychange', () => {
        if (document.hidden) {
          this.stopPing();
        } else if (this.ws && this.ws.readyState === WebSocket.OPEN) {
          this.startPing();
        }
      });
    }
  }

  /**
   * 开始心跳检测
   */
  private startPing(): void {
    this.stopPing();
    this.pingInterval = setInterval(() => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        this.send('ping');
      }
    }, 30000); // 每30秒发送一次ping
  }

  /**
   * 停止心跳检测
   */
  private stopPing(): void {
    if (this.pingInterval) {
      clearInterval(this.pingInterval);
      this.pingInterval = null;
    }
  }

  /**
   * 判断是否应该重连
   * @param closeCode 关闭代码
   * @returns boolean
   */
  private shouldReconnect(closeCode: number): boolean {
    // 1000: 正常关闭
    // 1001: 端点离开
    // 1006: 异常关闭
    const reconnectableCodes = [1006, 1001];
    return reconnectableCodes.includes(closeCode) && 
           this.reconnectAttempts < this.maxReconnectAttempts;
  }

  /**
   * 计划重连
   */
  private scheduleReconnect(): void {
    if (!this.sessionId) return;

    this.reconnectAttempts++;
    const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1); // 指数退避

    console.log(`Scheduling reconnect attempt ${this.reconnectAttempts} in ${delay}ms`);
    
    setTimeout(() => {
      if (this.sessionId) {
        this.connect(this.sessionId).catch(error => {
          console.error('Reconnect failed:', error);
        });
      }
    }, delay);
  }

  /**
   * 发送队列中的消息
   */
  private flushMessageQueue(): void {
    while (this.messageQueue.length > 0 && this.ws && this.ws.readyState === WebSocket.OPEN) {
      const message = this.messageQueue.shift();
      if (message) {
        this.ws.send(message);
      }
    }
  }

  /**
   * 获取连接状态
   * @returns WebSocket状态
   */
  getReadyState(): number {
    return this.ws ? this.ws.readyState : WebSocket.CLOSED;
  }

  /**
   * 是否已连接
   * @returns boolean
   */
  isConnected(): boolean {
    return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
  }

  /**
   * 获取当前会话ID
   * @returns 会话ID
   */
  getSessionId(): string | null {
    return this.sessionId;
  }
}

// 创建单例实例
export const comparisonWebSocketService = new ComparisonWebSocketService();

// 导出WebSocket状态常量
export const WS_STATES = {
  CONNECTING: 0,
  OPEN: 1,
  CLOSING: 2,
  CLOSED: 3
} as const;